#pragma once
#include <queue>
#include <unistd.h>
#include "Log.hpp"
#include "Thread.hpp" //using pthread lib

using namespace log_ddsm;

enum NUM
{
    //默认线程池内线程个数
    DEFAULTNUM = 10
};

/// @brief
/// @tparam T:任务类型
//懒汉模式设计单例ThreadPool

template <typename T>
class ThreadPool
{
    
private:
    void LockQueue() // 加锁
    {
        pthread_mutex_lock(&_taskqueue_mutex);
    }
    void UnLockQueue() // 解锁
    {
        pthread_mutex_unlock(&_taskqueue_mutex);
    }
    void Sleep() // 在条件变量_taskqueue_cond下等待
    {
        pthread_cond_wait(&_taskqueue_cond, &_taskqueue_mutex);
    }

    void WakeUp() // 叫醒一个进程
    {
        pthread_cond_signal(&_taskqueue_cond);
    }
    void WakeUpAll() // 叫醒所有线程
    {
        pthread_cond_broadcast(&_taskqueue_cond);
    }
    bool IsEmpty()
    {
        return _taskqueue.empty();
    }

    // thread将要执行的函数逻辑
    void HandlerTask(const std::string &name)
    {
        // 一直循环：等待任务——执行任务——等待任务，直到运行到break逻辑
        while (true)
        {
            LockQueue();

            /*  优先级上，先考虑任务队列不为空，只有任务队列为空，再考虑是否要线程退出*/
            while (IsEmpty() && _isrunning) // 没有任务则等待,while——在唤醒之后先判断是否队列仍然有任务，否则再次等待
            {
                _sleep_num++;
                Sleep();
                _sleep_num--;
            }
            if (IsEmpty() && !_isrunning)
            {
                UnLockQueue();

                LOG(DEBUG, "thread quit\n");
                // cout << "thread quit" << endl;
                break;
            }

            T t; // 从taskqueue中获取任务
            t = _taskqueue.front();
            _taskqueue.pop();
            UnLockQueue();

            // 执行任务，在解锁之后进行，执行任务要与从队列中获取任务并发
            // 不能在临界区中进行
            t();

            //LOG(DEBUG, "%s", name.c_str());
            // cout << name << " : ";
            //t.Debug();
        }
    }
    // 缺省个数——10
    ThreadPool(size_t threadnum)
        : _threadnum(threadnum), _taskqueue(), _isrunning(false), _sleep_num(0) // 初始化列中调用has a的构造？？
    {
        // 初始化
        pthread_mutex_init(&_taskqueue_mutex, nullptr);
        pthread_cond_init(&_taskqueue_cond, nullptr);
    }
    // 初始化线程池
    void Init()
    {
        ThreadMoudle::func_t func = std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1);
        for (int i = 0; i < _threadnum; ++i)
        {
            std::string name = "thread - " + std::to_string(i + 1);

            _threads.emplace_back(name, func); // 减少一次拷贝，直接在vector内构造
            // usleep(10000);
            // cout << "emplaced i+1 :" << i + 1 << endl;
        }
    }

    // 开始运行
    void Start()
    {
        _isrunning = true; // 单进程访问不需要保护

        for (int i = 0; i < _threadnum; ++i)
        {
            _threads[i].Start();
            LOG(DEBUG, "thread - %d started \n", i + 1);
        }
    }

public:
    static ThreadPool<T> *GetInstance()
    {
        if (_ptp == nullptr)
        {
            LockGuard lockguard(&_sig_mutex);
            if (_ptp == nullptr)
            {
                LOG(INFO, "create threadspool\n");
                _ptp = new ThreadPool<T>(DEFAULTNUM);//线程安全问题
                _ptp->Init();
                _ptp->Start();
            }
        }
        else
        {
            LOG(INFO, "get threadspool\n");
        }
        return _ptp;
    }

    // 停止运行
    void Stop()
    {
        LockQueue();
        _isrunning = false;
        WakeUpAll();
        UnLockQueue();
    }

    // 向任务队列加入任务
    void PushTask(const T &in)
    {
        LockQueue();
        if (_isrunning == true) // 防止出现线程池想要退出但是 却被一直分配任务，导致无法退出
        {
            _taskqueue.push(in); // 加入任务
            if (_sleep_num > 0)
                WakeUp();
        }
        UnLockQueue();
    }

    ~ThreadPool()
    {
        for (int i = 0; i < _threadnum; ++i)
        {
            LOG(INFO, "thread-%d joined\n", i + 1);
            _threads[i].Join();
        }
        pthread_mutex_destroy(&_taskqueue_mutex);
        pthread_cond_destroy(&_taskqueue_cond);
    }

private:
    size_t _threadnum;                          // 线程池中线程的个数
    std::vector<ThreadMoudle::Thread> _threads; // vector维护线程池

    std::queue<T> _taskqueue; // 任务队列
    bool _isrunning;          // 标识线程池是否在运行

    /*多线程对taskqueue访问需要整体使用——加锁*/
    pthread_mutex_t _taskqueue_mutex; // 用于维护taskqueue的mutex cond
    pthread_cond_t _taskqueue_cond;

    int _sleep_num; // 休眠的线程个数

    static ThreadPool<T> *_ptp; // 单例对象
    static pthread_mutex_t _sig_mutex;
};

// 静态成员在类外初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::_ptp = nullptr;

// 第一次保护获取单例的mutex
template <class T>
pthread_mutex_t ThreadPool<T>::_sig_mutex = PTHREAD_MUTEX_INITIALIZER;
